#include <stdio.h>

#include <atlstr.h>
#include <atlpath.h>

#include "Usage.h"
#include "Switches.h"
#include "Recurser.h"
#include "ResultReporter.h"
#include "CmdLineMatcher.h"

#include "tdd.h"

CString MakeAbsolute(const CString& path)
{
    WCHAR full[MAX_PATH] = {0};
	::GetFullPathName(path, MAX_PATH, full, NULL);
    return full;
}

int Dump(const CPath& path)
{
    class DumperDiscriminator : public TDD::Discriminator
    {
        virtual bool WantTest(const TDD::UnitTestInfo& uti)
        {
            wprintf(L"%S.%S\n", uti.group, uti.testname);
            return false;
        }
    } dd;
    class DumperReporter : public TDD::Reporter
    {
        virtual void ForEachTest(const TDD::UnitTestInfo&) {}
        virtual void ForEachFailure(const TDD::TestFailure&) {}
    } dr;
	TestRunner tr(dd, dr);
	tr.RunTests(path);
	return 0;
}

int __cdecl main(int argc, char *argv[])
{
    if (argc < 2)
		return Usage::Display();

	CPath path = MakeAbsolute(CString(argv[1])); // allow incremental paths

	Switches switches;
	if (switches.IsDumpMode())
		return Dump(path);
	
	struct Console
	{
		void operator()(const CString& cs) { wprintf(cs); }
	} console;
	CmdLineMatcher clm(argc-1, argv+1);

	if (switches.IsSingleDllMode())
	{
		ResultReporterT<Console> rr(console);
		TestRunner tr(clm, rr);
		tr.RunTests(path);
		return (rr.TestsRun() == 0) || (rr.TestsFailed() != 0) ? -1 : 0;
	}
	else if (switches.IsRecursiveMode())
	{
		ResultReporterT<Console> rr(console);
		Recurser recurser(path, clm, rr);
		recurser.Recurse();
		return (rr.TestsRun() == 0) || (rr.TestsFailed() != 0) ? -1 : 0;
	}
	else
	{
		return Usage::Display();
	}
}